package com.iceframework.core.config;

import java.io.Serializable;

import org.apache.catalina.LifecycleException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.iceframework.core.support.redis.ObjectRedisSerializer;

/**
 * 创建RedisConfig配置类，将RedisTemplate的setValueSerializer设置成ObjectRedisSerializer转换类。
 * 
 * @author Palo
 *
 */
@Configuration
public class RedisConfiguration {

	protected final Log logger = LogFactory.getLog(getClass());

	// 获取根域名
	@Value("${web.checkRedis}")
	private String checkRedis;

	/**
	 * 配置RedisTemplate实例
	 * 
	 * @param factory
	 * @return
	 * @throws LifecycleException
	 * @throws InterruptedException 
	 */
	@Bean
	public RedisTemplate<Serializable, Object> redisTemplate(RedisConnectionFactory connectionFactory) throws LifecycleException, InterruptedException {
		long start = System.currentTimeMillis();
		RedisTemplate<Serializable, Object> template = new RedisTemplate<Serializable, Object>();
		template.setConnectionFactory(connectionFactory);
		template.afterPropertiesSet();
		template.setKeySerializer(new StringRedisSerializer());
		template.setValueSerializer(new ObjectRedisSerializer());
		long end = System.currentTimeMillis();
		logger.info("配置RedisTemplate实例完成，用时" + (end - start) + "毫秒");
		// 检查Redis是否启动
		if (StringUtils.isNotBlank(checkRedis) && "true".equals(checkRedis.toLowerCase())) {
			checkRedisStartupStatus(template, true);
		} else {
			logger.info("已跳过Redis检查");
		}
		return template;
	}

	/**
	 * Redis启动检查程序
	 * 
	 * @param template
	 * @param isNecessary
	 * @throws LifecycleException
	 * @throws InterruptedException 
	 */
	private void checkRedisStartupStatus(RedisTemplate<Serializable, Object> template, Boolean isNecessary) throws LifecycleException, InterruptedException {
		// 检查Redis启动状态
		if (isNecessary) {
			logger.info("[*]Checking Redis is Startup");
			long start = System.currentTimeMillis();
			long end = 0L;
			while (true) {
				try {
					template.execute(new RedisCallback<Object>() {
						public String doInRedis(RedisConnection connection) {
							return connection.ping();
						}
					});
					break;
				} catch (RedisConnectionFailureException e) {
					logger.error("ping :" + e.getMessage());
					Thread.sleep(3000);
				}
			}
			end = System.currentTimeMillis();
			logger.info("Redis Started ,Check Millisecond:" + (end - start));
		}
	}
}